package com.cencat.order.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cencat.order.dto.DispatchDTO;
import com.cencat.order.entity.Dispatch;
import com.cencat.order.mapper.DispatchMapper;
import com.cencat.order.service.DispatchService;
import com.cencat.order.vo.DispatchVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 智能派单业务逻辑实现类
 * 
 * @author cencat
 * @date 2024-01-20
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DispatchServiceImpl extends ServiceImpl<DispatchMapper, Dispatch> implements DispatchService {

    private final DispatchMapper dispatchMapper;

    @Override
    public IPage<DispatchVO> getDispatchPage(Page<DispatchVO> page, String dispatchCode, Long routeId,
                                            Long driverId, Long orderId, Integer dispatchStatus,
                                            LocalDateTime startTime, LocalDateTime endTime) {
        log.info("分页查询派单列表，参数：dispatchCode={}, routeId={}, driverId={}, orderId={}, dispatchStatus={}, startTime={}, endTime={}",
                dispatchCode, routeId, driverId, orderId, dispatchStatus, startTime, endTime);
        
        IPage<DispatchVO> result = dispatchMapper.selectDispatchPage(page, dispatchCode, routeId, driverId,
                orderId, dispatchStatus, startTime, endTime);
        
        log.info("分页查询派单列表完成，总数：{}", result.getTotal());
        return result;
    }

    @Override
    public DispatchVO getByDispatchCode(String dispatchCode) {
        log.info("根据派单编号查询派单信息，dispatchCode={}", dispatchCode);
        
        if (!StringUtils.hasText(dispatchCode)) {
            log.warn("派单编号不能为空");
            return null;
        }
        
        DispatchVO result = dispatchMapper.selectByDispatchCode(dispatchCode);
        log.info("根据派单编号查询派单信息完成，result={}", result != null ? "找到" : "未找到");
        return result;
    }

    @Override
    public List<DispatchVO> getByRouteId(Long routeId, Integer dispatchStatus, LocalDateTime startTime, LocalDateTime endTime) {
        log.info("根据路线ID查询派单列表，routeId={}, dispatchStatus={}, startTime={}, endTime={}",
                routeId, dispatchStatus, startTime, endTime);
        
        if (routeId == null) {
            log.warn("路线ID不能为空");
            return List.of();
        }
        
        List<DispatchVO> result = dispatchMapper.selectByRouteId(routeId, dispatchStatus, startTime, endTime);
        log.info("根据路线ID查询派单列表完成，数量：{}", result.size());
        return result;
    }

    @Override
    public List<DispatchVO> getByDriverId(Long driverId, Integer dispatchStatus, LocalDateTime startTime, LocalDateTime endTime) {
        log.info("根据司机ID查询派单列表，driverId={}, dispatchStatus={}, startTime={}, endTime={}",
                driverId, dispatchStatus, startTime, endTime);
        
        if (driverId == null) {
            log.warn("司机ID不能为空");
            return List.of();
        }
        
        List<DispatchVO> result = dispatchMapper.selectByDriverId(driverId, dispatchStatus, startTime, endTime);
        log.info("根据司机ID查询派单列表完成，数量：{}", result.size());
        return result;
    }

    @Override
    public List<DispatchVO> getByOrderId(Long orderId, Integer dispatchStatus) {
        log.info("根据订单ID查询派单列表，orderId={}, dispatchStatus={}", orderId, dispatchStatus);
        
        if (orderId == null) {
            log.warn("订单ID不能为空");
            return List.of();
        }
        
        List<DispatchVO> result = dispatchMapper.selectByOrderId(orderId, dispatchStatus);
        log.info("根据订单ID查询派单列表完成，数量：{}", result.size());
        return result;
    }

    @Override
    public List<DispatchVO> getByStatus(Integer dispatchStatus, LocalDateTime startTime, LocalDateTime endTime, Integer limit) {
        log.info("根据状态查询派单列表，dispatchStatus={}, startTime={}, endTime={}, limit={}",
                dispatchStatus, startTime, endTime, limit);
        
        List<DispatchVO> result = dispatchMapper.selectByStatus(dispatchStatus, startTime, endTime, limit);
        log.info("根据状态查询派单列表完成，数量：{}", result.size());
        return result;
    }

    @Override
    public Map<String, Object> getDispatchStatistics(Long routeId, Long driverId, Integer dispatchStatus,
                                                    LocalDateTime startTime, LocalDateTime endTime) {
        log.info("查询派单统计信息，routeId={}, driverId={}, dispatchStatus={}, startTime={}, endTime={}",
                routeId, driverId, dispatchStatus, startTime, endTime);
        
        Map<String, Object> result = dispatchMapper.selectDispatchStatistics(routeId, driverId, dispatchStatus,
                startTime, endTime);
        
        log.info("查询派单统计信息完成");
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createDispatch(DispatchDTO dispatchDTO) {
        log.info("创建派单信息，dispatchDTO={}", dispatchDTO);
        
        if (dispatchDTO == null) {
            log.warn("派单信息不能为空");
            return false;
        }
        
        // 检查派单编号是否已存在
        if (StringUtils.hasText(dispatchDTO.getDispatchCode())) {
            DispatchVO existingDispatch = dispatchMapper.selectByDispatchCode(dispatchDTO.getDispatchCode());
            if (existingDispatch != null) {
                log.warn("派单编号已存在：{}", dispatchDTO.getDispatchCode());
                return false;
            }
        }
        
        Dispatch dispatch = new Dispatch();
        BeanUtils.copyProperties(dispatchDTO, dispatch);
        dispatch.setCreateTime(LocalDateTime.now());
        dispatch.setUpdateTime(LocalDateTime.now());
        dispatch.setDeleted(false);
        
        boolean result = save(dispatch);
        log.info("创建派单信息完成，result={}", result);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateDispatch(Long dispatchId, DispatchDTO dispatchDTO) {
        log.info("更新派单信息，dispatchId={}, dispatchDTO={}", dispatchId, dispatchDTO);
        
        if (dispatchId == null || dispatchDTO == null) {
            log.warn("派单ID和派单信息不能为空");
            return false;
        }
        
        Dispatch existingDispatch = getById(dispatchId);
        if (existingDispatch == null) {
            log.warn("派单不存在：{}", dispatchId);
            return false;
        }
        
        Dispatch dispatch = new Dispatch();
        BeanUtils.copyProperties(dispatchDTO, dispatch);
        dispatch.setId(dispatchId);
        dispatch.setUpdateTime(LocalDateTime.now());
        
        boolean result = updateById(dispatch);
        log.info("更新派单信息完成，result={}", result);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean cancelDispatch(Long dispatchId, String cancelReason) {
        log.info("取消派单，dispatchId={}, cancelReason={}", dispatchId, cancelReason);
        
        if (dispatchId == null) {
            log.warn("派单ID不能为空");
            return false;
        }
        
        Dispatch dispatch = getById(dispatchId);
        if (dispatch == null) {
            log.warn("派单不存在：{}", dispatchId);
            return false;
        }
        
        // 检查派单状态是否可以取消
        if (dispatch.getDispatchStatus() != null && dispatch.getDispatchStatus() >= 3) {
            log.warn("派单状态不允许取消，当前状态：{}", dispatch.getDispatchStatus());
            return false;
        }
        
        dispatch.setDispatchStatus(9); // 9表示已取消
        dispatch.setCancelReason(cancelReason);
        dispatch.setCancelTime(LocalDateTime.now());
        dispatch.setUpdateTime(LocalDateTime.now());
        
        boolean result = updateById(dispatch);
        log.info("取消派单完成，result={}", result);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> intelligentDispatch(Long routeId, Long orderId, Map<String, Object> dispatchRules) {
        log.info("智能派单，routeId={}, orderId={}, dispatchRules={}", routeId, orderId, dispatchRules);
        
        if (routeId == null || orderId == null) {
            log.warn("路线ID和订单ID不能为空");
            return Map.of("success", false, "message", "路线ID和订单ID不能为空");
        }
        
        try {
            // 这里应该实现智能派单算法，暂时返回模拟数据
            Long recommendedDriverId = findBestDriver(routeId, orderId, dispatchRules);
            
            if (recommendedDriverId == null) {
                return Map.of("success", false, "message", "未找到合适的司机");
            }
            
            // 创建派单
            DispatchDTO dispatchDTO = new DispatchDTO();
            dispatchDTO.setDispatchCode("DISP" + System.currentTimeMillis());
            dispatchDTO.setRouteId(routeId);
            dispatchDTO.setOrderId(orderId);
            dispatchDTO.setDriverId(recommendedDriverId);
            dispatchDTO.setDispatchStatus(1); // 1表示已派单
            dispatchDTO.setDispatchTime(LocalDateTime.now());
            dispatchDTO.setMatchScore(new BigDecimal("85.5"));
            
            boolean created = createDispatch(dispatchDTO);
            
            Map<String, Object> result = Map.of(
                    "success", created,
                    "dispatchId", created ? System.currentTimeMillis() : null,
                    "driverId", recommendedDriverId,
                    "matchScore", 85.5,
                    "estimatedTime", 30,
                    "message", created ? "智能派单成功" : "智能派单失败"
            );
            
            log.info("智能派单完成，result={}", result);
            return result;
            
        } catch (Exception e) {
            log.error("智能派单异常", e);
            return Map.of("success", false, "message", "智能派单异常：" + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean manualDispatch(Long routeId, Long orderId, Long driverId, String dispatchRemark) {
        log.info("手动派单，routeId={}, orderId={}, driverId={}, dispatchRemark={}",
                routeId, orderId, driverId, dispatchRemark);
        
        if (routeId == null || orderId == null || driverId == null) {
            log.warn("路线ID、订单ID和司机ID不能为空");
            return false;
        }
        
        // 检查司机是否可用
        // 这里应该调用司机服务检查司机状态
        
        DispatchDTO dispatchDTO = new DispatchDTO();
        dispatchDTO.setDispatchCode("DISP" + System.currentTimeMillis());
        dispatchDTO.setRouteId(routeId);
        dispatchDTO.setOrderId(orderId);
        dispatchDTO.setDriverId(driverId);
        dispatchDTO.setDispatchStatus(1); // 1表示已派单
        dispatchDTO.setDispatchTime(LocalDateTime.now());
        dispatchDTO.setDispatchRemark(dispatchRemark);
        dispatchDTO.setDispatchType(2); // 2表示手动派单
        
        boolean result = createDispatch(dispatchDTO);
        log.info("手动派单完成，result={}", result);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> batchDispatch(List<Long> routeIds, List<Long> orderIds, Map<String, Object> batchRules) {
        log.info("批量派单，routeIds={}, orderIds={}, batchRules={}", routeIds, orderIds, batchRules);
        
        if ((routeIds == null || routeIds.isEmpty()) && (orderIds == null || orderIds.isEmpty())) {
            log.warn("路线ID列表和订单ID列表不能同时为空");
            return Map.of("success", false, "message", "路线ID列表和订单ID列表不能同时为空");
        }
        
        int successCount = 0;
        int failCount = 0;
        
        try {
            // 这里应该实现批量派单逻辑
            if (routeIds != null && !routeIds.isEmpty()) {
                for (Long routeId : routeIds) {
                    // 模拟批量派单
                    boolean success = Math.random() > 0.2; // 80%成功率
                    if (success) {
                        successCount++;
                    } else {
                        failCount++;
                    }
                }
            }
            
            Map<String, Object> result = Map.of(
                    "success", true,
                    "totalCount", successCount + failCount,
                    "successCount", successCount,
                    "failCount", failCount,
                    "successRate", successCount * 100.0 / (successCount + failCount)
            );
            
            log.info("批量派单完成，result={}", result);
            return result;
            
        } catch (Exception e) {
            log.error("批量派单异常", e);
            return Map.of("success", false, "message", "批量派单异常：" + e.getMessage());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean redispatch(Long dispatchId, Long newDriverId, String redispatchReason) {
        log.info("重新派单，dispatchId={}, newDriverId={}, redispatchReason={}",
                dispatchId, newDriverId, redispatchReason);
        
        if (dispatchId == null || newDriverId == null) {
            log.warn("派单ID和新司机ID不能为空");
            return false;
        }
        
        Dispatch dispatch = getById(dispatchId);
        if (dispatch == null) {
            log.warn("派单不存在：{}", dispatchId);
            return false;
        }
        
        // 更新派单信息
        dispatch.setDriverId(newDriverId);
        dispatch.setRedispatchReason(redispatchReason);
        dispatch.setRedispatchTime(LocalDateTime.now());
        dispatch.setUpdateTime(LocalDateTime.now());
        
        boolean result = updateById(dispatch);
        log.info("重新派单完成，result={}", result);
        return result;
    }

    @Override
    public Map<String, Object> calculateDriverMatch(Long driverId, Long routeId, Long orderId) {
        log.info("计算司机匹配度，driverId={}, routeId={}, orderId={}", driverId, routeId, orderId);
        
        if (driverId == null || routeId == null || orderId == null) {
            log.warn("司机ID、路线ID和订单ID不能为空");
            return Map.of("success", false, "message", "参数不能为空");
        }
        
        // 这里应该实现实际的匹配度计算算法
        double matchScore = calculateMatchScore(driverId, routeId, orderId);
        
        Map<String, Object> result = Map.of(
                "success", true,
                "matchScore", matchScore,
                "matchLevel", getMatchLevel(matchScore),
                "factors", Map.of(
                        "distance", 85,
                        "experience", 90,
                        "rating", 88,
                        "availability", 95
                ),
                "recommendation", matchScore >= 80 ? "推荐" : "不推荐"
        );
        
        log.info("计算司机匹配度完成，matchScore={}", matchScore);
        return result;
    }

    @Override
    public Map<String, Object> analyzeDispatchEfficiency(LocalDateTime startTime, LocalDateTime endTime,
                                                        Map<String, Object> analysisParameters) {
        log.info("派单效率分析，startTime={}, endTime={}, analysisParameters={}",
                startTime, endTime, analysisParameters);
        
        // 这里应该实现实际的效率分析
        Map<String, Object> result = Map.of(
                "success", true,
                "totalDispatches", 150,
                "successfulDispatches", 135,
                "successRate", 90.0,
                "averageDispatchTime", 5.2,
                "averageMatchScore", 82.5,
                "efficiency", "良好",
                "suggestions", List.of(
                        "优化司机分布",
                        "提高匹配算法精度",
                        "加强司机培训"
                )
        );
        
        log.info("派单效率分析完成");
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchUpdateDispatchStatus(List<Long> dispatchIds, Integer dispatchStatus) {
        log.info("批量更新派单状态，dispatchIds={}, dispatchStatus={}", dispatchIds, dispatchStatus);
        
        if (dispatchIds == null || dispatchIds.isEmpty() || dispatchStatus == null) {
            log.warn("派单ID列表和状态不能为空");
            return false;
        }
        
        boolean result = dispatchMapper.batchUpdateDispatchStatus(dispatchIds, dispatchStatus) > 0;
        log.info("批量更新派单状态完成，result={}", result);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean softDeleteDispatch(Long dispatchId) {
        log.info("软删除派单信息，dispatchId={}", dispatchId);
        
        if (dispatchId == null) {
            log.warn("派单ID不能为空");
            return false;
        }
        
        Dispatch dispatch = new Dispatch();
        dispatch.setId(dispatchId);
        dispatch.setDeleted(true);
        dispatch.setUpdateTime(LocalDateTime.now());
        
        boolean result = updateById(dispatch);
        log.info("软删除派单信息完成，result={}", result);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchSoftDeleteDispatches(List<Long> dispatchIds) {
        log.info("批量软删除派单信息，dispatchIds={}", dispatchIds);
        
        if (dispatchIds == null || dispatchIds.isEmpty()) {
            log.warn("派单ID列表不能为空");
            return false;
        }
        
        List<Dispatch> dispatches = dispatchIds.stream()
                .map(id -> {
                    Dispatch dispatch = new Dispatch();
                    dispatch.setId(id);
                    dispatch.setDeleted(true);
                    dispatch.setUpdateTime(LocalDateTime.now());
                    return dispatch;
                })
                .collect(Collectors.toList());
        
        boolean result = updateBatchById(dispatches);
        log.info("批量软删除派单信息完成，result={}", result);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean restoreDispatch(Long dispatchId) {
        log.info("恢复已删除的派单信息，dispatchId={}", dispatchId);
        
        if (dispatchId == null) {
            log.warn("派单ID不能为空");
            return false;
        }
        
        Dispatch dispatch = new Dispatch();
        dispatch.setId(dispatchId);
        dispatch.setDeleted(false);
        dispatch.setUpdateTime(LocalDateTime.now());
        
        boolean result = updateById(dispatch);
        log.info("恢复已删除的派单信息完成，result={}", result);
        return result;
    }

    @Override
    public List<Map<String, Object>> getDispatchOperationLogs(Long dispatchId, LocalDateTime startTime,
                                                             LocalDateTime endTime, Integer limit) {
        log.info("查询派单操作日志，dispatchId={}, startTime={}, endTime={}, limit={}",
                dispatchId, startTime, endTime, limit);
        
        if (dispatchId == null) {
            log.warn("派单ID不能为空");
            return List.of();
        }
        
        List<Map<String, Object>> result = dispatchMapper.selectDispatchOperationLogs(dispatchId, startTime, endTime, limit);
        log.info("查询派单操作日志完成，数量：{}", result.size());
        return result;
    }

    /**
     * 查找最佳司机
     */
    private Long findBestDriver(Long routeId, Long orderId, Map<String, Object> dispatchRules) {
        // 这里应该实现实际的司机匹配算法
        // 暂时返回模拟数据
        return 1001L;
    }

    /**
     * 计算匹配得分
     */
    private double calculateMatchScore(Long driverId, Long routeId, Long orderId) {
        // 这里应该实现实际的匹配得分计算
        // 暂时返回模拟数据
        return 75.0 + Math.random() * 20; // 75-95分
    }

    /**
     * 获取匹配等级
     */
    private String getMatchLevel(double matchScore) {
        if (matchScore >= 90) {
            return "优秀";
        } else if (matchScore >= 80) {
            return "良好";
        } else if (matchScore >= 70) {
            return "一般";
        } else {
            return "较差";
        }
    }
}